home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / sphigs / sph_srgp.lha / srgp / src / srgp_input_X.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-09  |  13.7 KB  |  485 lines

  1. #include "HEADERS.h"
  2. #include "srgplocal.h"
  3. #include <ctype.h>
  4.  
  5. /** LOW-LEVEL "DRIVERS"
  6.  
  7.    SRGP__activateDevice (deviceID)
  8.       Must be called when device is going from INACTIVE to active, OR
  9.          when device is changed from one active mode to the other.
  10.  
  11.    SRGP__deactivateDevice (deviceID)
  12.       Must be called only when device is going from active to inactive.
  13.  
  14.  
  15.    SRGP__handleRawEvents (boolean in_waitEvent_call)
  16.       This function nevers enters a wait state.
  17.       It examines all the events on the "raw"
  18.          queue: the queue of the underlying graphics package
  19.      (e.g., X11, Mac).
  20.       Exception: it may not handle all the raw events.
  21.          It exits as soon as it sees a valid trigger situation.
  22.       It returns a device ID IF AND ONLY IF...
  23.      1) the appl. is in a call to SRGP_waitEvent(), AND
  24.      2) a valid trigger for a device currently in Event mode
  25.         has been encountered.
  26.       IF it does return a device ID, THEN...
  27.          It automatically sets the proper value for either
  28.          srgp__get_locator_measure or
  29.          srgp__get_keyboard_measure
  30.      in preparation for the application's ensuing call to 
  31.          SRGP_get...()
  32.       Another exception: it may "pass over" some raw events and
  33.          just leave them in the raw queue.
  34.       It will pass over a raw event IF AND ONLY IF...
  35.      1) the appl. is not in a call to SRGP_waitEvent(), AND
  36.      2) the event is a valid trigger for a device
  37.         currently in Event mode.
  38.       Another possibility is that it will discard a raw event
  39.          without processing it at all.
  40.       It will discard a raw event IF AND ONLY IF...
  41.          The event is for a device that is currently inactive.
  42. **/
  43.  
  44. #define BACKSPACE_KEY     127
  45. #define CARRIAGE_RETURN  13
  46.  
  47. #define KEYS        (KeyPressMask)
  48. #define MOTION_HINT    (PointerMotionHintMask|PointerMotionMask)
  49. #define MOTION_ALL    (PointerMotionMask)
  50. #define BUTTONS (ButtonPressMask|ButtonReleaseMask|OwnerGrabButtonMask)
  51. #define DEFAULT    (StructureNotifyMask|EnterWindowMask)
  52.  
  53. /** X SELECT INPUT MASKS
  54.   I am always looking for keyboard presses (X events) because
  55.   some keys are always active, allowing the user to press F6
  56.   (for example) to turn on tracing at run-time, etc.
  57.   
  58.   When the locator is in sample mode w/o rubber echo, I need
  59.       pointer-motion *hints* only.
  60.   When the locator is using rubber echo, I need all pointer motion events.
  61.   When the locator is in event mode and not echoed rubberly,
  62.       I only need button-event reports.
  63. **/
  64.  
  65. static unsigned long 
  66. selectinputmask 
  67.  [3] /*inputMode*/
  68.  [2] /*boolean:rubberon?*/ = {
  69.    /* input mode: INACTIVE */   {0L, 0L},
  70.    /* input mode: SAMPLE */       {MOTION_ALL|BUTTONS, MOTION_ALL|BUTTONS},
  71.    /* input mode: EVENT */       {BUTTONS, MOTION_ALL|BUTTONS}
  72. };
  73.  
  74. #define SelectInput(LOCMODE,RUBBERON)   \
  75.    XSelectInput (srgpx__display, srgpx__screenwin, \
  76.          selectinputmask[LOCMODE][RUBBERON?1:0]|KEYS|DEFAULT)
  77.  
  78.  
  79. void
  80. SRGP__initInputDrivers()
  81. {
  82.    /* INITIALIZE X INPUT */
  83.    SelectInput (INACTIVE,FALSE);
  84. }
  85.  
  86.  
  87.  
  88. void
  89. SRGP__updateInputSelectionMask()
  90. {
  91.    SelectInput (srgp__cur_mode[LOCATOR], 
  92.         srgp__cur_locator_echo_type > CURSOR);
  93. }
  94.  
  95.  
  96.  
  97.  
  98. /** RAW-LEVEL DEACTIVATION OF A DEVICE
  99. Responsible for erasing echo, and resetting device's measure to the
  100.    hardwired default.
  101. Upon entry, the device's cur_mode is its old value (has not been
  102.    changed yet)!  And this procedure does not change it!
  103. **/
  104.  
  105. void
  106. SRGP__deactivateDevice (int device)
  107. {
  108.    XEvent xev;
  109.  
  110.    switch (device) {
  111.       
  112.     case LOCATOR:
  113.       SRGP__disableLocatorRubberEcho();
  114.       SRGP__disableLocatorCursorEcho();
  115.       srgp__cur_locator_measure.position = 
  116.          SRGP_defPoint(srgp__canvasTable[0].max_xcoord>>1,
  117.                srgp__canvasTable[0].max_ycoord>>1);
  118.       SelectInput(INACTIVE,FALSE);
  119.       /* Delete all currently queued locator-related raw events. */
  120.       while (XCheckMaskEvent(srgpx__display, MOTION_ALL|BUTTONS, &xev));
  121.       break;
  122.        
  123.     case KEYBOARD:
  124.       SRGP__disableKeyboardEcho();
  125.       srgp__cur_keyboard_measure.buffer[0] = '\0';
  126.       bzero (srgp__cur_keyboard_measure.modifier_chord,
  127.          sizeof(srgp__cur_keyboard_measure.modifier_chord));
  128.       break;
  129.    }
  130. }
  131.  
  132.  
  133.  
  134.  
  135.  
  136. /** RAW-LEVEL ACTIVATION OF A DEVICE
  137. Called whenever:
  138.   a device is placed into EVENT or SAMPLE mode...
  139.      a) when previously inactive
  140.      b) when previously active but in a different mode
  141. Responsible for initiating echo and setting X's selection mask.
  142. Upon entry, the device's echo info and mode has already been set
  143.   to their new values.
  144. **/
  145.  
  146. void
  147. SRGP__activateDevice (int device)
  148. {
  149.    switch (device) {
  150.     case LOCATOR:
  151.       SRGP__disableLocatorCursorEcho();
  152.       SRGP__disableLocatorRubberEcho();
  153.       SRGP__enableLocatorCursorEcho();
  154.       SRGP__enableLocatorRubberEcho();
  155.       SRGP__updateInputSelectionMask();
  156.       break;
  157.        
  158.     case KEYBOARD:
  159.       SRGP__enableKeyboardEcho();
  160.       break;
  161.    }
  162. }
  163.  
  164.  
  165.  
  166.  
  167.  
  168. void
  169. SRGP__updateRawCursorPosition ()
  170. {
  171.    srgp__cur_Xcursor_x = srgp__cur_locator_measure.position.x;
  172.    srgp__cur_Xcursor_y = 
  173.       SCREENFIXED(srgp__cur_locator_measure.position.y);
  174.    XWarpPointer
  175.       (srgpx__display,
  176.        None, srgpx__screenwin,
  177.        0,0,0,0,
  178.        srgp__cur_Xcursor_x, srgp__cur_Xcursor_y);
  179.    SRGP__updateLocatorRubberEcho();
  180. }
  181.  
  182.  
  183.  
  184.  
  185. static   XEvent xevent;
  186. static   int xstrcount;
  187. static   char buffer[50];
  188. static   KeySym keysym;
  189. static   unsigned long mask;
  190. static   boolean in_wait_event;
  191.  
  192.  
  193.  
  194. void
  195. SRGP__updateLocationKnowledge ()
  196. {
  197.    Window rw, cw;
  198.    int xr, yr;
  199.    unsigned int keys_buttons;
  200.  
  201.    XQueryPointer (srgpx__display, srgpx__screenwin,
  202.           &rw, &cw, &xr, &yr,
  203.           &srgp__cur_Xcursor_x, &srgp__cur_Xcursor_y, 
  204.           &keys_buttons);
  205.    srgp__cur_locator_measure.position.x = srgp__cur_Xcursor_x;
  206.    srgp__cur_locator_measure.position.y = SCREENFIXED(srgp__cur_Xcursor_y);
  207.    
  208.    srgp__dirty_location = FALSE;
  209. }
  210.  
  211.  
  212.  
  213.  
  214. static inputDevice HandleXButtonEvent (buttonStatus TRANSITION_TYPE) 
  215. {
  216.    int which_button;
  217.    boolean do_return_event_notice = FALSE;
  218.  
  219.  
  220.    which_button = xevent.xbutton.button - 1;
  221.  
  222.    if (srgp__cur_mode[LOCATOR] != EVENT)
  223.       goto change_cur_measure;
  224.  
  225.    if (((srgp__cur_locator_button_mask >> which_button) & 1) == 0)
  226.       goto change_cur_measure;
  227.  
  228.    if ( ! in_wait_event) {
  229.       XPutBackEvent (srgpx__display, &xevent);
  230.       mask &=  ~(BUTTONS);
  231.       return NO_DEVICE;
  232.    }
  233.  
  234.    do_return_event_notice = TRUE;
  235.  
  236.  change_cur_measure:
  237.    srgpx__cur_time = xevent.xbutton.time;
  238.    srgp__cur_locator_measure.button_chord[which_button] = TRANSITION_TYPE;
  239.    srgp__cur_locator_measure.button_of_last_transition = which_button;
  240.    srgp__cur_locator_measure.modifier_chord[SHIFT] =
  241.       (xevent.xbutton.state&ShiftMask?TRUE:FALSE); 
  242.    srgp__cur_locator_measure.modifier_chord[CONTROL] =  
  243.       (xevent.xbutton.state&ControlMask?TRUE:FALSE); 
  244.    srgp__cur_locator_measure.modifier_chord[META] =  
  245.       (xevent.xbutton.state&Mod1Mask?TRUE:FALSE); 
  246.    srgp__cur_locator_measure.position.x = 
  247.       xevent.xbutton.x; 
  248.    srgp__cur_locator_measure.position.y = 
  249.       srgp__canvasTable[0].max_ycoord - xevent.xbutton.y; 
  250.    if (do_return_event_notice) {
  251.       srgp__get_locator_measure = srgp__cur_locator_measure; 
  252.       return LOCATOR; 
  253.    }
  254.    return NO_DEVICE;
  255. }
  256.  
  257.  
  258.  
  259. static inputDevice HandleRawModeKeyEvent (void)
  260. {
  261.    boolean do_return_event_notice = FALSE;
  262.    
  263.    if (srgp__cur_mode[KEYBOARD] != EVENT)
  264.       goto change_cur_measure;
  265.    
  266.    if ( ! in_wait_event) {
  267.       XPutBackEvent (srgpx__display, &xevent);
  268.       mask &=  ~(KEYS);
  269.       return NO_DEVICE;
  270.    }
  271.  
  272.    do_return_event_notice = TRUE;
  273.    
  274.  change_cur_measure:
  275.    srgp__cur_keyboard_measure.buffer[0] = *buffer;
  276.    srgp__cur_keyboard_measure.buffer[1] = '\0';
  277.    srgp__cur_keyboard_measure.modifier_chord[SHIFT] =
  278.       (xevent.xkey.state&ShiftMask?TRUE:FALSE);
  279.    srgp__cur_keyboard_measure.modifier_chord[CONTROL] =
  280.       (xevent.xkey.state&ControlMask?TRUE:FALSE);
  281.    srgp__cur_keyboard_measure.modifier_chord[META] =
  282.       (xevent.xkey.state&Mod1Mask?TRUE:FALSE);
  283.    if (do_return_event_notice) {
  284.       strcpy (srgp__get_keyboard_measure.buffer, 
  285.           srgp__cur_keyboard_measure.buffer);
  286.       bcopy (srgp__cur_keyboard_measure.modifier_chord,
  287.          srgp__get_keyboard_measure.modifier_chord,
  288.          sizeof(srgp__get_keyboard_measure.modifier_chord));
  289.       srgp__get_keyboard_measure.position =
  290.      srgp__cur_keyboard_measure.position;
  291.       return KEYBOARD;
  292.    }
  293.    return NO_DEVICE;
  294. }
  295.  
  296.  
  297. static inputDevice HandleProcModeKeyEvent (void)
  298. {
  299.    boolean do_return_event_notice = FALSE;
  300.    
  301.    switch (buffer[0]) {
  302.     case CARRIAGE_RETURN:
  303.       if (srgp__cur_mode[KEYBOARD] != EVENT)
  304.      goto erase_cur_measure;
  305.       if (in_wait_event)
  306.      do_return_event_notice = TRUE;
  307.       else {
  308.      XPutBackEvent (srgpx__display, &xevent);
  309.      mask &=  ~KEYS;
  310.      return NO_DEVICE;
  311.       }
  312.       if (do_return_event_notice) {
  313.      strcpy (srgp__get_keyboard_measure.buffer, 
  314.          srgp__cur_keyboard_measure.buffer);
  315.      srgp__get_keyboard_measure.position =
  316.         srgp__cur_keyboard_measure.position;
  317.       }
  318.     erase_cur_measure:
  319.       srgp__cur_keyboard_measure.buffer[0] = '\0';
  320.       srgp__cur_keyboard_measure_length = 0;
  321.       SRGP__updateKeyboardEcho();
  322.       if (do_return_event_notice)
  323.      return KEYBOARD;
  324.       break;
  325.       
  326.     case BACKSPACE_KEY:
  327.       if (srgp__cur_keyboard_measure_length > 0) {
  328.      srgp__cur_keyboard_measure_length =
  329.         srgp__cur_keyboard_measure_length - 1;
  330.      srgp__cur_keyboard_measure.buffer
  331.         [srgp__cur_keyboard_measure_length] =
  332.            '\0';
  333.      SRGP__updateKeyboardEcho();
  334.       }
  335.       break;
  336.       
  337.     default:
  338.       /* CHECK: IS THE KEY PRINTABLE ASCII? */
  339.       if ((isprint(*buffer)) &&
  340.       (srgp__cur_keyboard_measure_length < MAX_STRING_SIZE)) {
  341.      srgp__cur_keyboard_measure.buffer
  342.         [srgp__cur_keyboard_measure_length] = 
  343.            *buffer;
  344.      srgp__cur_keyboard_measure_length++;
  345.      srgp__cur_keyboard_measure.buffer
  346.         [srgp__cur_keyboard_measure_length] = 
  347.            '\0';
  348.      SRGP__updateKeyboardEcho();
  349.       }
  350.       break;
  351.    }
  352.    return NO_DEVICE;
  353. }
  354.    
  355.  
  356.  
  357.  
  358.  
  359.  
  360. /** SRGP__handleRawEvents
  361.       This function nevers enters a wait state, unless it has been
  362.          called as a result of SRGP_waitEvent(FOREVER).
  363.       It examines all the events on the "raw"
  364.          queue: the queue of the underlying graphics package
  365.      (e.g., X11, Mac).
  366.       Exception: it may not handle all the raw events.
  367.          It exits as soon as it sees a valid trigger situation.
  368.       It returns a device ID IF AND ONLY IF...
  369.      1) the appl. is in a call to SRGP_waitEvent(), AND
  370.      2) a valid trigger for a device currently in Event mode
  371.         has been encountered.
  372.       IF it does return a device ID, THEN...
  373.          It automatically sets the proper value for either
  374.          srgp__get_locator_measure or
  375.          srgp__get_keyboard_measure
  376.      in preparation for the application's ensuing call to 
  377.          SRGP_get...()
  378.       Another exception: it may "pass over" some raw events and
  379.          just leave them in the raw queue.
  380.       It will pass over a raw event IF AND ONLY IF...
  381.      1) the appl. is not in a call to SRGP_waitEvent(), AND
  382.      2) the event is a valid trigger for a device
  383.         currently in Event mode.
  384.       Another possibility is that it will discard a raw event
  385.          without processing it at all.
  386.       It will discard a raw event IF AND ONLY IF...
  387.          The event is for a device that is currently inactive.
  388. **/
  389.  
  390. int
  391.    SRGP__handleRawEvents (boolean inwaitevent, boolean forever)
  392. {
  393.    inputDevice id;
  394.    
  395.    in_wait_event = inwaitevent;
  396.    mask = (KEYS|MOTION_ALL|DEFAULT|BUTTONS);
  397.    
  398.    while (1) {
  399.       
  400.       if (forever && inwaitevent) {
  401.          XMaskEvent (srgpx__display, mask, &xevent);
  402.       }
  403.       else {
  404.          if ( ! XCheckMaskEvent (srgpx__display, mask, &xevent))
  405.         return NO_DEVICE;
  406.       }
  407.       
  408.       switch (xevent.type) {
  409.      
  410.        case EnterNotify:
  411.      /* IF ON COLOR SYSTEM:
  412.         When cursor enters screen canvas, install SRGP colormap. */
  413.      if ((srgp__available_depth > 1) && 
  414.          (srgp__available_depth == srgp__application_depth))
  415.         XInstallColormap (srgpx__display, srgpx__colormap);
  416.      break;
  417.      
  418.        case MotionNotify:
  419.      /* WE CAN ASSUME LOCATOR IS ACTIVE IF WE GET HERE. */
  420.      srgpx__cur_time = xevent.xmotion.time;
  421.      if (xevent.xmotion.is_hint)
  422.         /* WE CAN ASSUME RUBBER-ECHO IS OFF IF WE GET HERE. */
  423.         /* WE CAN ALSO ASSUME LOCATOR IS IN SAMPLE MODE IF WE GET HERE. */
  424.         srgp__dirty_location = TRUE;
  425.      else {
  426.         srgp__cur_Xcursor_x = xevent.xmotion.x;
  427.         srgp__cur_Xcursor_y = xevent.xmotion.y;
  428.         srgp__cur_locator_measure.position.x = srgp__cur_Xcursor_x;
  429.         srgp__cur_locator_measure.position.y = 
  430.            SCREENFIXED(srgp__cur_Xcursor_y);
  431.         SRGP__updateLocatorRubberEcho();
  432.      }
  433.      break;
  434.      
  435.        case ButtonPress:
  436.      if (id = HandleXButtonEvent (DOWN))
  437.         return id;
  438.      break;
  439.      
  440.        case ButtonRelease:
  441.      if (id = HandleXButtonEvent (UP))
  442.         return id;
  443.      break;
  444.      
  445.        case MappingNotify:
  446.      XRefreshKeyboardMapping (&xevent.xmapping);
  447.      break;
  448.      
  449.        case ConfigureNotify:
  450.      /* WE ONLY WISH TO REACT IF TRULY INVOLVED RESIZING (not just move) */
  451.      if (xevent.xconfigure.width == srgp__canvasTable[0].max_xcoord+1) 
  452.         if (xevent.xconfigure.height == srgp__canvasTable[0].max_ycoord+1) 
  453.            break;
  454.      
  455.      /* IF WE GET HERE, we wish to change the dimensions as recorded in
  456.         the canvas table, being careful if the screen canvas is currently
  457.         active. */
  458.      SRGP__reactToScreenResize
  459.         (xevent.xconfigure.width, xevent.xconfigure.height);
  460.      break;
  461.      
  462.        case KeyPress:
  463.      xstrcount = XLookupString (&xevent.xkey, buffer, 50, &keysym, 0);
  464.      /* HERE, CHECK FOR keysym==FKEY for interesting FKEYS. */
  465.      if (srgp__cur_mode[KEYBOARD] == INACTIVE) 
  466.         break;
  467.      if (xstrcount != 1)
  468.         break;
  469.      
  470.      srgpx__cur_time = xevent.xkey.time;
  471.      srgp__cur_keyboard_measure.position.x = xevent.xkey.x;
  472.      srgp__cur_keyboard_measure.position.y = SCREENFIXED(xevent.xkey.y);
  473.      
  474.      if (srgp__cur_keyboard_processing_mode == RAW) {
  475.         if (id = HandleRawModeKeyEvent())
  476.            return id;
  477.      }
  478.      else {
  479.         if (id = HandleProcModeKeyEvent())
  480.            return id;
  481.      }
  482.       }
  483.    }
  484. }
  485.